﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using CamShared;
using System.Diagnostics;
using DavuxLib;


namespace CamServer
{
    class CamHost
    {
        public static List<ICamera> Cameras = new List<ICamera>();

        static List<ICameraConnector> Connectors = null;
        static List<ICameraFilter> Filters = null;
        static List<ICameraOutput> Outputs = null;
        
        public static bool Initialize()
        {
            Trace.WriteLine("Loading Plugins...");

            Connectors = DavuxLib.Plugin.Load<ICameraConnector>();
            Filters = DavuxLib.Plugin.Load<ICameraFilter>();
            Outputs = DavuxLib.Plugin.Load<ICameraOutput>();

            if (Connectors == null ||
                Filters == null ||
                Outputs == null)
            {
                Trace.WriteLine("Error loading plugins:");
                Trace.WriteLine("Connectors: " + Connectors);
                Trace.WriteLine("Filters: " + Filters);
                Trace.WriteLine("Outputs: " + Outputs);
                return false;
            }

            foreach(ICameraConnector ic in Connectors)
            {
                try
                {
                    ic.CameraDiscovered += new CamShared.CamShared.CameraDiscovered(ic_CameraDiscovered);
                    ic.DetectCameras();
                }
                catch (Exception ex)
                {
                    Trace.WriteLine("Error in camera detection: " + ex);
                }
            }

            foreach (ICameraFilter icf in Filters)
            {
                try
                {
                    icf.OnNewFrame += new CamShared.CamShared.RaiseRame(fi_OnNewFrame);
                }
                catch (Exception ex)
                {
                    Trace.WriteLine("Error adding OnNewFrame handler to filter: " + ex);
                }
            }

            Trace.WriteLine("-----------------------");
            return true;
        }

        static void ic_CameraDiscovered(ICamera cam, ICameraConnector conn)
        {
            Trace.WriteLine("Found:     " + cam.Name);

            if (Settings.Get(cam.Name + "|Enabled", true))
            {
                cam.OnError += new CamShared.CamShared.CameraError(cam_OnError);
                cam.OnFrame += new CamShared.CamShared.FrameReceived(cam_OnFrame);
                Cameras.Add(cam);




                foreach (ICameraOutput ico in Outputs)
                {
                    try
                    {
                        ico.CameraAttached(cam);
                    }
                    catch (Exception ex)
                    {
                        Trace.WriteLine("Error attaching camera to output " + ico.Name + ": " + ex);
                    }
                }

                if (MainForm.CurrentInstance != null)
                {
                    MainForm.CurrentInstance.OnCameraAdded(cam);
                }
            }
            else
            {
                Trace.WriteLine("NoLoad: " + cam.Name);
            }
            //Settings.SetRestartRequired(cam.Name + "|Enabled");
        }



        static void fi_OnNewFrame(ICamera cam, System.Drawing.Image frame)
        {
            foreach (ICameraOutput co in Outputs)
            {
                try
                {
                    co.FrameReceived(cam, frame);
                }
                catch (Exception ex)
                {
                    Trace.WriteLine("A camera output had an error on FrameReceived: " + ex);
                }
            }
        }

        static void cam_OnFrame(ICamera cam, System.Drawing.Image frame)
        {
            foreach (ICameraFilter fi in Filters)
            {
                try
                {
                    frame = fi.FrameReceived(cam, frame);
                }
                catch (Exception ex)
                {
                    Trace.WriteLine("A camera filter had an error on FrameReceived: " + ex);
                }
            }
            foreach (ICameraOutput co in Outputs)
            {
                try
                {
                    co.FrameReceived(cam, frame);
                }
                catch (Exception ex)
                {
                    Trace.WriteLine("A camera output had an error on FrameReceived (OnFrame): " + ex);
                }
            }
        }

        static void cam_OnError(ICamera cam, string Error, bool Fatal)
        {
            foreach (ICameraOutput co in Outputs)
            {
                try
                {
                    co.ErrorOccured(cam, Error, Fatal);
                }
                catch (Exception ex)
                {
                    Trace.WriteLine("A camera output had an error on ErrorOccured (cam_OnError): " + ex);
                }
            }
        }

        internal static void Dispose()
        {
            Trace.WriteLine("Unloading plugins");
            foreach (ICameraConnector conn in Connectors)
            {
                try
                {
                    conn.Dispose();
                }
                catch { }
            }
            foreach (ICameraFilter fi in Filters)
            {
                try
                {
                    fi.Dispose();
                }
                catch { }
            }
            foreach (ICameraOutput ou in Outputs)
            {
                try
                {
                    ou.Dispose();
                }
                catch { }
            }
        }
    }
}
